﻿using BCCommon;
using BCCommon.Enums;
using BCCommon.Extensions;
using BCCommon.FMISEnums;
using BCCommon.OAEnums;
using BCCommon.OAEnums.Workflow;
using BCData.MySql.Admin;
using BCData.MySql.Dictionary;
using BCData.OA.ApplyOrder;
using BCData.OA.BusinessTypeRecord;
using BCData.OA.Reimbursement;
using BCData.OA.TeamWorks.FMISTaskRecord;
using BCData.OA.TeamWorks.TaskReceiverRecord;
using BCData.OA.TeamWorks.TaskRecord;
using BCData.OA.TeamWorks.TaskRejectRecord;
using BCData.OA.Workflow.WorkflowActivityInstanceReference;
using BCData.SCM.VehicleSaleCheckList;
using BCDto.FMIS.SOBSetting;
using BCDto.MySql.Admin;
using BCDto.OA.ApplyOrder;
using BCDto.OA.Reimbursement;
using BCDto.OA.TeamWorks.TaskRecord;
using BCDto.OA.TeamWorks.TaskRejectRecord;
using BCDto.OA.Workflow.WorkflowOperation;
using BCEntity.OA.ApplyOrder;
using BCEntity.OA.Reimbursement;
using BCEntity.OA.TeamWorks.TaskRecord;
using BCEntity.OA.Workflow.WorkflowActivityInstanceReference;
using BCService.Utils;
using BCService.WorkflowEngine;
using System;
using System.Collections.Generic;
using System.Linq;

namespace BCService.OA.ApplyOrder.ReimbursementService
{
    /// <summary>
    /// 报销申请单服务
    /// </summary>
    public class ReimbursementApplyOrderService : IReimbursementApplyOrderService
    {
        private readonly IApplyOrderData applyOrderData;
        private readonly ITaskRecordData taskRecordData;
        private readonly ITaskReceiverRecordData taskReceiverRecordData;
        private readonly ITaskRejectRecordData taskRejectRecordData;
        private readonly IWorkflowEngineService workflowEngineService;
        private readonly IDictionaryReferenceData dictionaryReferenceData;
        private readonly IAdminData adminData;
        private readonly IWorkflowActivityInstanceReferenceData workflowActivityInstanceReferenceData;
        private readonly IReimbursementRecordData reimbursementRecordData;
        private readonly IVehicleSaleCheckListData vehicleSaleCheckListData;
        private readonly IFMISTaskRecordData iFMISTaskRecordData;
        private readonly IBusinessTypeRecordData businessTypeRecordData;

        public ReimbursementApplyOrderService(IApplyOrderData applyOrderData,
          ITaskRecordData taskRecordData,
          ITaskReceiverRecordData taskReceiverRecordData,
          ITaskRejectRecordData taskRejectRecordData,
          IWorkflowEngineService workflowEngineService,
          IDictionaryReferenceData dictionaryReferenceData,
          IWorkflowActivityInstanceReferenceData workflowActivityInstanceReferenceData,
          IAdminData adminData,
          IReimbursementRecordData reimbursementRecordData,
          IVehicleSaleCheckListData vehicleSaleCheckListData,
          IFMISTaskRecordData iFMISTaskRecordData,
          IBusinessTypeRecordData businessTypeRecordData)
        {
            this.applyOrderData = applyOrderData;
            this.taskRecordData = taskRecordData;
            this.taskReceiverRecordData = taskReceiverRecordData;
            this.taskRejectRecordData = taskRejectRecordData;
            this.workflowEngineService = workflowEngineService;
            this.dictionaryReferenceData = dictionaryReferenceData;
            this.workflowActivityInstanceReferenceData = workflowActivityInstanceReferenceData;
            this.adminData = adminData;
            this.reimbursementRecordData = reimbursementRecordData;
            this.vehicleSaleCheckListData = vehicleSaleCheckListData;
            this.iFMISTaskRecordData = iFMISTaskRecordData;
            this.businessTypeRecordData = businessTypeRecordData;
        }

        public ApplyOrderDto Create(AdminDto admin, ApplyOrderRequestDto dto)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 创建报销申请
        /// </summary>
        /// <param name="admin">当前登录员工</param>
        /// <param name="dto">报销信息</param>
        /// <param name="sobSetting">账套信息</param>
        /// <returns></returns>
        public ApplyOrderDto Create(AdminDto admin, ApplyOrderRequestDto dto, SOBSettingDto sobSetting)
        {
            string typeStr = ((OAApplyOrderType)Enum.Parse(typeof(OAApplyOrderType), dto.Type.ToString())).GetDescriptionString();
            if (dto.Reimbursement == null)
            {
                throw new ArgumentException("报销明细不能为空。");
            }
            if (dto.Reimbursement.Amount <= 0)
            {
                throw new ArgumentException("报销金额不能为空。");
            }
            if (this.businessTypeRecordData.GetEntityByTypeNameAndSobSettingIdAsync(dto.Reimbursement.Category, sobSetting.SobSettingId).GetAwaiter().GetResult() == null)
            {
                throw new ArgumentException("报销业务类型不存在。");
            }
            if (dto.Copiers != null && dto.Copiers.Length > 0)
            {
                foreach (var item in dto.Copiers)
                {
                    var receiverAdmin = adminData.GetAdmin(item);
                    if (receiverAdmin == null)
                    {
                        throw new ArgumentException("抄送人信息不存在");
                    }
                }
            }
            #region 创建申请单信息
            ApplyOrderEntity res = this.MarkApplyOrder(admin, dto, typeStr);
            if (res != null)
            {
                return res.As<ApplyOrderDto>();
            }
            #endregion

            return new ApplyOrderDto();
        }

        /// <summary>
        /// 获取指定申请单详情信息
        /// </summary>
        /// <param name="admin">当前管理员</param>
        /// <param name="applyOrderId">申请单Id</param>
        /// <returns></returns>
        public ApplyOrderViewDto GetDetail(AdminDto admin, long applyOrderId)
        {
            var applyOrder = applyOrderData.GetById(applyOrderId).GetAwaiter().GetResult();
            if (!applyOrder.IsRead)
            {
                applyOrder = applyOrderData.UpdateApplyOrderRead(applyOrderId, admin.FullName, admin.AdminId).GetAwaiter().GetResult();
            }
            ApplyOrderViewDto view = new ApplyOrderViewDto
            {
                ApplyOrderInfo = applyOrder.As<ApplyOrderDto>(),
                BusinessData = reimbursementRecordData.GetEntityByApplyCode(applyOrder.ApplyCode).GetAwaiter().GetResult().As<ReimbursementRecordDto>()
            };
            var approvalRecords = taskRecordData.GetTaskRecordEntitiesByReferenceNoAsync(applyOrder.ApplyCode).GetAwaiter().GetResult().As<List<ApplyOrderApprovalRecordDto>>();
            if (approvalRecords.Any())
            {
                view.TaskRecords = approvalRecords.OrderBy(c => c.CreateTime).ToList();
                long workflowActivityInstanceId = approvalRecords.First().WorkflowActivityInstanceId;
                view.Copiers = taskReceiverRecordData.GetByWorkflowActivityInstanceId(workflowActivityInstanceId).GetAwaiter().GetResult().As<List<TaskReceiverRecordDto>>();
                foreach (var item in view.TaskRecords.Where(s => s.HandleStatus == OATaskHandleStatus.Dismissed))
                {
                    item.RejectInfo = taskRejectRecordData.GetByWorkflowActivityInstanceId(workflowActivityInstanceId, item.TaskRecordNo).GetAwaiter().GetResult().As<TaskRejectRecordDto>();
                }
            }
            return view;
        }

        /// <summary>
        /// 审批申请单
        /// </summary>
        /// <param name="admin"></param>
        /// <param name="applyOrderId"></param>
        /// <returns></returns>
        public ApplyOrderViewDto Pass(AdminDto admin, long applyOrderId)
        {
            var applyOrder = applyOrderData.GetById(applyOrderId).GetAwaiter().GetResult();
            if (applyOrder.Status == OAApplyOrderStatus.Done)
            {
                throw new ArgumentException("申请单已处理完成，不能重复审批。");
            }
            //工作流任务
            var taskRecord = taskRecordData.GetByReferenceNoAndTaskExecuterAdminId(applyOrder.ApplyCode, admin.AdminId).GetAwaiter().GetResult().As<TaskRecordDto>();
            if (taskRecord == null)
            {
                throw new ArgumentException("任务单信息不存在或执行人不正确。");
            }
            this.workflowEngineService.Execution(new WorkflowOperationRequestDto { HandleStatus = OATaskHandleOperationStatus.Handled, TaskRecordNo = taskRecord.TaskRecordNo });
            /**  TODO：推送未配置
             if (newTask.HandleStatus == OATaskHandleStatus.Handled)
             {
                 //推送给发起人审核              
                 pushMessageSendService.PushMessageForStaffApplication(applyRecod.AdminName, applyRecod.AdminId, PushMessageType.AttendanceRemedyCheckInPassed);
                 //推送给抄送人
                 var copiers = taskReceiverRecordData.GetByWorkflowActivityInstanceId(taskRecord.WorkflowActivityInstanceId).GetAwaiter().GetResult().As<List<TaskReceiverRecordEntity>>();
                 if (copiers.Any())
                 {               
                 pushMessageSendService.PushMessageForStaffApplication(applyRecod.AdminName, applyRecod.AdminId, PushMessageType.AttendanceRemedyCheckInCopiersNotify, copiers.Select(s => s.ReceiverAdminId).ToArray());
                 }
             }
             **/
            return this.GetDetail(admin, applyOrder.ApplyOrderId);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="admin"></param>
        /// <param name="applyOrderId"></param>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ApplyOrderViewDto Rejected(AdminDto admin, long applyOrderId, ApplyOrderRejectRequestDto dto)
        {
            var applyOrder = applyOrderData.GetById(applyOrderId).GetAwaiter().GetResult();
            //工作流任务
            var taskRecord = taskRecordData.GetByReferenceNoAndTaskExecuterAdminId(applyOrder.ApplyCode, admin.AdminId).GetAwaiter().GetResult().As<TaskRecordDto>();
            if (taskRecord == null)
            {
                throw new ArgumentException("任务单信息不存在或执行人不正确。");
            }
            this.workflowEngineService.Execution(new WorkflowOperationRequestDto { HandleStatus = OATaskHandleOperationStatus.Rejected, TaskRecordNo = taskRecord.TaskRecordNo, Remark = dto.RejectReason });
            return this.GetDetail(admin, applyOrder.ApplyOrderId);
        }

        #region 创建申请单信息
        private ApplyOrderEntity MarkApplyOrder(AdminDto admin, ApplyOrderRequestDto dto, string typeStr)
        {
            if (dto.Reimbursement.VehicleSaleContractNo.IsNotNull())
            {
                //校验销售合同编号
                var checkVehicle = vehicleSaleCheckListData.GetEntityByVehicleSaleContractNoAsync(dto.Reimbursement.VehicleSaleContractNo).GetAwaiter().GetResult();
                if (checkVehicle == null)
                {
                    throw new ArgumentException("合同信息不存在。");
                }
            }
            ApplyOrderEntity entity = new ApplyOrderEntity
            {
                ApplyCode = RandomCode.GenerateOAApplyCode(),
                AdminId = admin.AdminId,
                AdminName = admin.FullName,
                DepartmentId = admin.DepartmentId.Value,
                DepartmentName = admin.Department.DepartmentName,
                Type = dto.Type.ToString(),
                CopierIds = dto.Copiers.IsNotNull() ? dto.Copiers.Length > 1 ? string.Join(",", dto.Copiers) : dto.Copiers[0].ToString() : "",
                Title = string.Format("{0}提交的{1}", admin.FullName, typeStr),
                Content = string.Format("报销金额:{0},报销类别:{1},报销说明:{2}", dto.Reimbursement.Amount, dto.Reimbursement.Category, dto.Reimbursement.Content),
                CompanyId = admin.CompanyId
            };
            var applyOrderResult = applyOrderData.InsertAsync(entity).GetAwaiter().GetResult();
            if (applyOrderResult != null)
            {
                var reimbursement = this.MakeReimbursementApply(admin, dto.Reimbursement, applyOrderResult.ApplyCode);
                if (reimbursement != null)
                {
                    this.MakeTaskOrder(admin, dto, reimbursement, applyOrderResult.ApplyCode, dto.Reimbursement.VehicleSaleContractNo.IsNotNull());
                }
            }
            return applyOrderResult;

        }

        #endregion

        #region 创建报销单申请信息

        private ReimbursementRecordEntity MakeReimbursementApply(AdminDto admin, ReimbursementRequestDto requestDto, string applyCode)
        {
            ReimbursementRecordEntity reimbursementRecordEntity = requestDto.As<ReimbursementRecordEntity>();

            reimbursementRecordEntity.ApplyCode = applyCode;
            reimbursementRecordEntity.AdminId = admin.AdminId;
            reimbursementRecordEntity.AdminName = admin.FullName;
            reimbursementRecordEntity.DepartmentId = admin.DepartmentId.Value;
            reimbursementRecordEntity.DepartmentName = admin.Department.DepartmentName;
            reimbursementRecordEntity.RemarkFiles = requestDto.RemarkFiles.IsNotNull() ? string.Join(",", requestDto.RemarkFiles) : string.Empty;
            reimbursementRecordEntity.PictureFiles = requestDto.PictureFiles.IsNotNull() ? string.Join(",", requestDto.PictureFiles) : string.Empty;
            reimbursementRecordEntity.CompanyId = admin.CompanyId;
            return reimbursementRecordData.InsertAsync(reimbursementRecordEntity).GetAwaiter().GetResult();
        }

        #endregion

        #region 创建工作流任务信息
        private void MakeTaskOrder(AdminDto admin, ApplyOrderRequestDto dto, ReimbursementRecordEntity reimbursement, string applyCode, bool isSale)
        {
            //创建任务工作流任务              
            string instanceNo = string.Empty;
            OATaskBusinessType key = isSale ? OATaskBusinessType.WorkflowBusiness_Reimbursement_Sale : OATaskBusinessType.WorkflowBusiness_Reimbursement_Normal;
            var dictionaryTask = this.dictionaryReferenceData.GetEntityAsync(key.ToString()).GetAwaiter().GetResult();
            long instanceId = this.workflowEngineService.InitWorkflowActivityInstance(admin, dictionaryTask.SearchKey, admin.CompanyId, false, RoleType.Admin, ref instanceNo);
            List<TaskReceiverRecordEntity> receivers = new List<TaskReceiverRecordEntity>();
            if (dto.Copiers.IsNotNull())
            {
                foreach (var item in dto.Copiers)
                {
                    var receiverAdmin = adminData.GetAdmin(item);
                    receivers.Add(new TaskReceiverRecordEntity
                    {
                        ReceiverRole = OATaskReceiverRole.Participant,
                        ReceiverAdminId = receiverAdmin.AdminId,
                        ReceiverAdminFullName = receiverAdmin.FullName,
                        TaskStep = 0,
                        CreateTime = DateTime.Now,
                        WorkflowActivityInstanceId = instanceId
                    });
                }
            }
            //创建报销单第一步任务
            FMISTaskRecordEntity fMISTaskRecordEntity = new FMISTaskRecordEntity
            {
                WorkflowActivityInstanceId = instanceId,
                TaskRecordNo = Guid.NewGuid().ToString(),
                TaskCategory = OATaskCategoryType.Finance,
                BusinessType = dictionaryTask.SearchKey,
                BusinessTypeName = dictionaryTask.ItemValue,
                TaskType = FMISTaskType.Payable,
                CurrentlyStep = 0,
                TaskRemark = string.Format("{0}费用报销", reimbursement.Category),
                TaskTypeName = FMISTaskType.Payable.GetDescriptionString(),
                PayableAmount = reimbursement.Amount,
                ActualPaidAmount = reimbursement.Amount,
                HandleStatus = OATaskHandleStatus.Handled,
                CompanyId = admin.CompanyId
            };
            if (reimbursement.VehicleSaleContractNo.IsNotNull())
            {
                var vehicleSaleCheckList = vehicleSaleCheckListData.GetEntityByVehicleSaleContractNoAsync(reimbursement.VehicleSaleContractNo).GetAwaiter().GetResult();
                fMISTaskRecordEntity.SaleContractNo = vehicleSaleCheckList.VehicleSaleContractNo;
                vehicleSaleCheckList.SaleUniqueCode = vehicleSaleCheckList.SaleUniqueCode;
            }
            var insertResult = iFMISTaskRecordData.Add(fMISTaskRecordEntity).GetAwaiter().GetResult();
            if (insertResult)
            {
                //增加抄送人信息
                iFMISTaskRecordData.InsertTaskReceiverAsync(receivers).GetAwaiter().GetResult();
                //指派
                var taskRecordEntities = this.iFMISTaskRecordData.Get(instanceId).GetAwaiter().GetResult();
                if (taskRecordEntities.Any())
                {
                    var newTaskRecordEntity = taskRecordEntities.First(p => p.CurrentlyStep == 0);
                    newTaskRecordEntity.TaskExecuterAdminId = admin.AdminId;
                    newTaskRecordEntity.TaskExecuterFullName = admin.FullName;
                    newTaskRecordEntity.StartTime = DateTime.Now;
                    if (this.iFMISTaskRecordData.UpdateStartTime(newTaskRecordEntity).GetAwaiter().GetResult())
                    {
                        this.taskRecordData.UpdateHandleStatus(newTaskRecordEntity.TaskRecordNo, OATaskHandleStatus.Handled).GetAwaiter().GetResult();
                    }
                }
                WorkflowActivityInstanceReferenceEntity referenceEntity = new WorkflowActivityInstanceReferenceEntity
                {
                    WorkflowActivityInstanceReferenceNo = instanceNo,
                    WorkflowActivityInstanceId = instanceId,
                    WorkflowType = "Finance",
                    BusinessType = dictionaryTask.Name,
                    ReferenceNo = applyCode,
                    ReferenceType = "System.String"
                };
                this.workflowActivityInstanceReferenceData.Add(referenceEntity).GetAwaiter().GetResult();
                this.workflowEngineService.NextStep(instanceId);
                this.workflowEngineService.Start(instanceId);
            }


        }
        #endregion
    }
}

